/**************************************************************************** 
* 
* Copyright (c) 2023  C*Core -   All Rights Reserved  
* 
* THIS SOFTWARE IS DISTRIBUTED "AS IS," AND ALL WARRANTIES ARE DISCLAIMED, 
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* 
* PROJECT     : CCFC2011BC           
* DESCRIPTION : CCFC2011BC swt low level drivers code 
* HISTORY     : Initial version
* @file     swt_lld.c
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
*
*****************************************************************************/
#include "swt_lld.h"
#include "IntcInterrupts.h"
/*===========================================================================*/
/* Driver exported variables.                                                */
/*===========================================================================*/

/**
 * @brief   SWT0 driver identifier.
 */
#if (SWT_USE_SWT0 == TRUE)
SWTDriver SWTD1;
#endif

/**
 * @brief   SWT1 driver identifier.
 */
#if (SWT_USE_SWT1 == TRUE)
SWTDriver SWTD2;
#endif

/**
 * @brief   SWT2 driver identifier.
 */
#if (SWT_USE_SWT2 == TRUE)
SWTDriver SWTD3;
#endif

/**
 * @brief   SWT3 driver identifier.
 */
#if (SWT_USE_SWT3 == TRUE)
SWTDriver SWTD4;
#endif

/*===========================================================================*/
/* Driver interrupt handlers.                                                */
/*===========================================================================*/
#if ((SWT0_INTERRUPT_MODE == TRUE) || (SWT1_INTERRUPT_MODE == TRUE) || (SWT2_INTERRUPT_MODE == TRUE) || (SWT3_INTERRUPT_MODE == TRUE))
static void SWT_Interrupt_Handler(const SWTDriver *swtd)
{
    /* Acknowledge the interrupt, no bit field access on TIF */
    swtd->swtp->IR.R = 1;
    /* call the callback, if set */
    if (swtd->swt_config->callback != NULL)
    {
        swtd->swt_config->callback(swtd);
    }
}
#endif

#if ((SWT_USE_SWT0 == TRUE) && (SWT0_INTERRUPT_MODE == TRUE))
/**
 * @brief   SWT0 interrupt handler.
 *
 * @isr
 */
IRQ_HANDLER(SWT0_HANDLER)/* PRQA S 1505*/
{
    IRQ_PROLOGUE();
    SWT_Interrupt_Handler(&SWTD1);
    IRQ_EPILOGUE();
}
#endif


/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/


/*******************************************************************************
 * @brief      SWT_LLD_Init  Low level swt driver initialisation.
 * @param[in]  SWTDriver *swtd, SWT_Config *config
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_Init(SWTDriver *swtd, SWT_Config *config)
{
#if (SWT_USE_SWT0 == TRUE)
    /* Set pointer to the SWTDriver object */
    swtd->swtp = &SWT;
    /* Running frequency */
    swtd->swt_freq = SWT0_FREQUENCY;
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Even not used, set MAPs to 1 */
    swtd->swtp->CR.R = 0xFF000000U;
    swtd->swt_config = config;
    /* Set timeout period. */
    swtd->swtp->TO.R = SWT_PERIOD_TO_TICKS((swtd->swt_freq), (config->timeout_period));
    /* Set the window period */
    if (swtd->swtp->CR.B.WND == 1U)
    {
        swtd->swtp->WN.B.WST = SWT_PERIOD_TO_TICKS((swtd->swt_freq), (config->window_period));
    }
#endif /* SWT_USE_SWT0 */
}

/*******************************************************************************
 * @brief      SWT_LLD_DeInit Low level swt driver deinitialisation
 * @param[in]  swtd      pointer to the @p SWTDriver object
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_DeInit(SWTDriver *swtd)
{
    /* Set fixed sequence feed dog */
    SWT_LLD_SetKeyedService(swtd, 0);
    /* Set normal watchdog mode */
    SWT_LLD_SetMode(swtd, 0);
    /* If time_out , reset */
    SWT_LLD_SetInterruptMode(swtd, 0);
    /* If invlid access, reset */
    SWT_LLD_SetInvalidAccess(swtd, 1);
    /* Freeze in debug */
    SWT_LLD_FreezeMode(swtd, 1);
    /* Countinue to run in Stop mode*/
    SWT_LLD_StopMode(swtd, 0);
    /* Stop SWT */
    SWT_LLD_Stop(swtd);
    /* Clear configuration stucture */
    swtd->swt_config = NULL;
}


/*******************************************************************************
 * @brief      SWT_LLD_DeInit Execute the watchdog fixed servicing sequence
 * @param[in]  swtd      pointer to the @p SWTDriver object
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_KeepAlive(const SWTDriver *swtd)
{
    /*Write sequence1 0xA602*/
    swtd->swtp->SR.R = SWT_SERVICE_KEY_1;
    /*Write sequence2 0xB480*/
    swtd->swtp->SR.R = SWT_SERVICE_KEY_2;
}

/*******************************************************************************
 * @brief      SWT_LLD_RandomKeepAlive Execute the watchdog random servicing 
 *             sequence
 * @param[in]  swtd      pointer to the @p SWTDriver object
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_RandomKeepAlive(const SWTDriver *swtd)
{
    static uint32_t serv_key = 0x0000;
    /* Calculate new key #1 */
    serv_key = NEW_SERVICE_KEY((serv_key));
    swtd->swtp->SR.R = serv_key;
    /* Calculate new key #2 */
    serv_key = NEW_SERVICE_KEY((serv_key));
    swtd->swtp->SR.R = serv_key;
}


/*******************************************************************************
 * @brief      SWT_LLD_Stop Stop the SWT peripheral
 * @param[in]  swtd      pointer to the @p SWTDriver object
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_Stop(SWTDriver *swtd)/* PRQA S 1505*/
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Clear configuration stucture */
    swtd->swt_config = NULL;
    /* Disable SWT */
    swtd->swtp->CR.B.WEN = 0;
}


/*******************************************************************************
 * @brief      SWT_LLD_ModuleEnable const SWTDriver *swtd
 * @param[in]  swtd      pointer to the @p SWTDriver object
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_ModuleEnable(const SWTDriver *swtd)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Enable SWT */
    swtd->swtp->CR.B.WEN = 1;
}

/*******************************************************************************
 * @brief      SWT_LLD_ModuleDisable Disable SWT
 * @param[in]  swtd      pointer to the @p SWTDriver object
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_ModuleDisable(const SWTDriver *swtd)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Disable SWT */
    swtd->swtp->CR.B.WEN = 0;
}

/*******************************************************************************
 * @brief      SWT_LLD_SetTimeOutPeriod Set SWT time_out value
 * @param[in]  swtd         pointer to the @p SWTDriver object
 *             timeout      time_out value
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_SetTimeOutPeriod(SWTDriver *swtd, uint32_t timeout)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set frequency 128000 */
    swtd->swt_freq = SWT0_FREQUENCY;
    /* Set configured timeout */
    swtd->swt_config->timeout_period = timeout;
    /* Set the time out period */
    swtd->swtp->TO.R = SWT_PERIOD_TO_TICKS((swtd->swt_freq), (swtd->swt_config->timeout_period));
}

/*******************************************************************************
 * @brief      SWT_LLD_SetWindowTime Set SWT window value
 * @param[in]  swtd   swtd pointer to the @p SWTDriver object
               window_time
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_SetWindowTime(SWTDriver *swtd, uint32_t window_time)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set frequency 128000 */
    swtd->swt_freq = SWT0_FREQUENCY;
    /* Set configured window time */
    swtd->swt_config->window_period = window_time;
    /* Set the window period */
    swtd->swtp->WN.B.WST = SWT_PERIOD_TO_TICKS((swtd->swt_freq), (swtd->swt_config->window_period));
}

/*******************************************************************************
 * @brief      SWT_LLD_SetKeyedService Set SWT feed dog mode
 * @param[in]  swtd   swtd pointer to the @p SWTDriver object
 *             keyed_service      mode of feeding dog
 *                               1:random   0:fixed
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_SetKeyedService(const SWTDriver *swtd, uint8_t keyed_service)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set mode of feeding dog */
    swtd->swtp->CR.B.KEY = keyed_service;
}

/*******************************************************************************
 * @brief      SWT_LLD_SetMode Set SWT  mode
 * @param[in]  swtd              swtd pointer to the @p SWTDriver object
 *             mode              mode of feeding dog
 *                               1:window   0:normal
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_SetMode(const SWTDriver *swtd, uint8_t mode)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set SWT mode */
    swtd->swtp->CR.B.WND = mode;
}


/*******************************************************************************
 * @brief      Set SWT interrupt mode
 * @param[in]  swtd              swtd pointer to the @p SWTDriver object
 *             mode              mode of feeding dog
 *                               1:window   0:normal
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_SetInterruptMode(const SWTDriver *swtd, uint8_t int_mode)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set SWT interrupt mode */
    swtd->swtp->CR.B.ITR = int_mode;
    if (int_mode == 1u)
    {
        /* Install interrupt handler for SWT*/
        INTC_InstallINTCInterruptHandler(SWT0_HANDLER, SWT0_INT_NUMBER, SWT0_IRQ_PRIO);
    }
}


/*******************************************************************************
 * @brief      Set way to handle when invalid access
 * @param[in]  swtd              swtd pointer to the @p SWTDriver object
 *             mode              mode of feeding dog
 *                               1:window   0:normal
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_SetInvalidAccess(const SWTDriver *swtd, uint8_t mode)/* PRQA S 1505*/
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set SWT interrupt mode */
    swtd->swtp->CR.B.RIA = mode;
}

/*******************************************************************************
 * @brief      Set Freeze mode
 * @param[in]  state              state of freeze
 *                               1:freeze in debug mode 
 *                               0:continue to run in debug mode 
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_FreezeMode(const SWTDriver *swtd, uint8_t state)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set SWT Freeze mode */
    swtd->swtp->CR.B.FRZ = state;
}

/*******************************************************************************
 * @brief   Set Stop mode
 * @param[in] state              state of stop
 *                               1:stop in STOP mode 
 *                               0:continue to run in STOP mode 
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void SWT_LLD_StopMode(const SWTDriver *swtd, uint8_t state)
{
    /* Clear the software lock bit */
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_1;
    swtd->swtp->SR.R = SWT_UNLOCK_KEY_2;
    /* Set SWT Stop mode */
    swtd->swtp->CR.B.STP = state;
}

